
package com.rrd.dw.azkaban.flow;

import java.awt.geom.Point2D;
import java.util.HashMap;
import java.util.Map;

public class Node {
    private final String id;
    private String jobSource;
    private String propsSource;

    private Point2D position = null;
    private int level;
    private int expectedRunTimeSec = 1;
    private String type;

    private String embeddedFlowId;

    public Node(String id) {
        this.id = id;
    }

    /**
     * Clones nodes
     *
     * @param node
     */
    public Node(Node clone) {
        this.id = clone.id;
        this.propsSource = clone.propsSource;
        this.jobSource = clone.jobSource;
    }

    public String getId() {
        return this.id;
    }

    public String getType() {
        return this.type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Point2D getPosition() {
        return this.position;
    }

    public void setPosition(Point2D position) {
        this.position = position;
    }

    public void setPosition(double x, double y) {
        this.position = new Point2D.Double(x, y);
    }

    public int getLevel() {
        return this.level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public String getJobSource() {
        return this.jobSource;
    }

    public void setJobSource(String jobSource) {
        this.jobSource = jobSource;
    }

    public String getPropsSource() {
        return this.propsSource;
    }

    public void setPropsSource(String propsSource) {
        this.propsSource = propsSource;
    }

    public void setExpectedRuntimeSec(int runtimeSec) {
        this.expectedRunTimeSec = runtimeSec;
    }

    public int getExpectedRuntimeSec() {
        return this.expectedRunTimeSec;
    }

    public void setEmbeddedFlowId(String flowId) {
        this.embeddedFlowId = flowId;
    }

    public String getEmbeddedFlowId() {
        return this.embeddedFlowId;
    }

    @SuppressWarnings("unchecked")
    public static Node fromObject(Object obj) {
        Map<String, Object> mapObj = (Map<String, Object>) obj;
        String id = (String) mapObj.get("id");

        Node node = new Node(id);
        String jobSource = (String) mapObj.get("jobSource");
        String propSource = (String) mapObj.get("propSource");
        String jobType = (String) mapObj.get("jobType");

        String embeddedFlowId = (String) mapObj.get("embeddedFlowId");

        node.setJobSource(jobSource);
        node.setPropsSource(propSource);
        node.setType(jobType);
        node.setEmbeddedFlowId(embeddedFlowId);

        Integer expectedRuntime = (Integer) mapObj.get("expectedRuntime");
        if (expectedRuntime != null) {
            node.setExpectedRuntimeSec(expectedRuntime);
        }

        Map<String, Object> layoutInfo = (Map<String, Object>) mapObj
            .get("layout");
        if (layoutInfo != null) {
            Double x = null;
            Double y = null;
            Integer level = null;

            try {
                x = Utils.convertToDouble(layoutInfo.get("x"));
                y = Utils.convertToDouble(layoutInfo.get("y"));
                level = (Integer) layoutInfo.get("level");
            } catch (ClassCastException e) {
                throw new RuntimeException("Error creating node " + id, e);
            }

            if (x != null && y != null) {
                node.setPosition(new Point2D.Double(x, y));
            }
            if (level != null) {
                node.setLevel(level);
            }
        }

        return node;
    }

    public Object toObject() {
        HashMap<String, Object> objMap = new HashMap<>();
        objMap.put("id", this.id);
        objMap.put("jobSource", this.jobSource);
        objMap.put("propSource", this.propsSource);
        objMap.put("jobType", this.type);
        if (this.embeddedFlowId != null) {
            objMap.put("embeddedFlowId", this.embeddedFlowId);
        }
        objMap.put("expectedRuntime", this.expectedRunTimeSec);

        HashMap<String, Object> layoutInfo = new HashMap<>();
        if (this.position != null) {
            layoutInfo.put("x", this.position.getX());
            layoutInfo.put("y", this.position.getY());
        }
        layoutInfo.put("level", this.level);
        objMap.put("layout", layoutInfo);

        return objMap;
    }
}
